package com.srp.common.utils;

import org.springframework.lang.NonNull;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class SMMealCodeUtil {

    /**
     * 解析云卡
     *
     * @param code 传进来的二维码
     * @return DataEvent 自定义返回值
     */
    public static String analytic(char[] code) {
        int size = 0;
        int codeLen, dwCrc16, dwCalcCrc16, wDataLen;
        char bCodeBuf1[], bCodeBuf2[], bCodeBuf3[];
        char bInbuf[] = {
                0x12, 0x34, 0x56, 0x78, 0x90
        };
        if (code.length >= 512) {
            return null;
        }
        codeLen = code.length;
        char bTempBuf[] = new char[codeLen];
        char bTimeBuf[] = new char[6];
        char bBuffer[] = new char[codeLen / 2];
        char bOutBuffer[] = new char[codeLen / 2];

        for (int i = 0; i < code.length; i++) {
            bTempBuf[i] = asscii2Hex(code[i]);
        }

        for (int i = 0; i < code.length / 2; i++) {
            bBuffer[i] = (char) (bTempBuf[size] << 4 | bTempBuf[size + 1]);
            size += 2;
        }

        String f = "FFFFFFFFFFFF";
        bCodeBuf1 = f.toCharArray();
        bCodeBuf2 = qrCodeDecodeKey(bInbuf, bInbuf.length, bCodeBuf1, bCodeBuf1.length);
        bCodeBuf3 = charToHexStr(bCodeBuf2);

        System.arraycopy(bBuffer, 0, bOutBuffer, 0, 4);

        char bBuffer2[] = new char[bBuffer.length - 4];

        System.arraycopy(bBuffer, 4, bBuffer2, 0, bBuffer2.length);

        char[] chars = qrCodeDecodeKey(bBuffer2, bBuffer2.length, bCodeBuf3, bCodeBuf3.length);

        System.arraycopy(chars, 0, bOutBuffer, 4, chars.length);

        System.arraycopy(bBuffer, code.length / 2 - 6, bOutBuffer, code.length / 2 - 6, 6);

        wDataLen = bOutBuffer[2] << 8 | bOutBuffer[3];
        dwCalcCrc16 = genCrc(chars, wDataLen - 2);
        dwCrc16 = ((bOutBuffer[wDataLen + 3] << 8) | bOutBuffer[wDataLen + 2]);

        if (dwCalcCrc16 == dwCrc16) {

            System.arraycopy(bOutBuffer, bOutBuffer.length - 6, bTimeBuf, 0, 6);

            char[] time = qrCodeDecodeKey(bTimeBuf, bTimeBuf.length, "4SM01ZJ".toCharArray(), "4SM01ZJ".toCharArray().length);

            String str = Integer.toString(time[0]) + "-" + Integer.toString(time[1]) + "-" + Integer.toString(time[2]) + " " + Integer.toString(time[3]) + ":" + Integer.toString(time[4]) + ":" + Integer.toString(time[5]);
            long times = string2Millis(str, "y-M-d H:m:s");

            /*if (System.currentTimeMillis() - times > (3000 * 100)) {
                System.out.println("二维码失效");
            } else {
                StringBuilder sb2 = new StringBuilder();
                for (int k = 0; k < chars.length; k++) {
                    String hexStr = Integer.toHexString(chars[k]);
                    int anInt = Integer.parseInt(hexStr, 16);
                    String string = String.format("%02x", anInt);
                    sb2.append(string);
                }
                String s = sb2.toString().toUpperCase();

                String accounts = s.substring(2, 10);

                String icNumber = s.substring(14, 22);
                Map<String, Object> map = new HashMap<>();
                map.put("accounts", accounts);
                map.put("ic_number", icNumber);
                return map;
            }*/

            StringBuilder sb2 = new StringBuilder();
            for (int k = 0; k < chars.length; k++) {
                String hexStr = Integer.toHexString(chars[k]);
                int anInt = Integer.parseInt(hexStr, 16);
                String string = String.format("%02x", anInt);
                sb2.append(string);
            }
            String s = sb2.toString().toUpperCase();

            String accounts = s.substring(2, 10);

            String icNumber = s.substring(14, 22);

            System.out.println(99);
            System.out.println(accounts);
            System.out.println(icNumber);
            System.out.println(s);
            System.out.println(199);
            return s;

        }
        return null;
    }

    private static int genCrc(char[] buf, int len) {
        char ch;
        int crc_reg = 0xFFFF;
        int CRCTable[] = {0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
                0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400};

        for (int i = 0; i < len; i++) {
            ch = buf[i];
            crc_reg = CRCTable[(ch ^ crc_reg) & 0x0f] ^ (crc_reg >> 4);
            crc_reg = CRCTable[((ch >> 4) ^ crc_reg) & 0x0f] ^ (crc_reg >> 4);
        }
        return crc_reg;
    }

    private static char[] qrCodeDecodeKey(char[] int_buf, int bInNum, char[] decode_key, int codenum) {
        char bTempBuf[] = int_buf;
        for (int i = 0; i < bInNum; i++) {
            for (int j = 0; j < codenum; j++) {
                bTempBuf[i] = (char) (bTempBuf[i] ^ decode_key[j]);
            }
        }
        return bTempBuf;
    }

    private static char[] charToHexStr(char[] int_buf) {
        StringBuilder sb = new StringBuilder();
        for (int k = 0; k < int_buf.length; k++) {
            sb.append(Integer.toHexString(int_buf[k]).toUpperCase());
        }
        return sb.toString().toCharArray();
    }


    private static char asscii2Hex(char temp) {
        char bResult;
        if (temp >= 'A' && temp <= 'F') {
            bResult = (char) (temp - 0X37);
        } else if (temp >= 'a' && temp <= 'f') {
            bResult = (char) (temp - 0x57);
        } else if (temp >= '0' && temp <= '9') {
            bResult = (char) (temp - 0x30);
        } else {
            bResult = 0;
        }
        return bResult;
    }


    public static long string2Millis(String time, String pattern) {
        try {
            return new SimpleDateFormat(pattern, Locale.getDefault()).parse(time).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 获取16进制日期
     * @return
     */
    public static String getDateHexStr() {
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
        String dateStr = sdf.format(now);
        String result = "";
        System.out.println(dateStr);
        for(Integer i = 0; i < 6; i++) {
            String hexStr = Integer.toHexString(Integer.parseInt(dateStr.substring(i * 2, (i + 1) * 2), 10));
            if (hexStr.length() < 2) hexStr = "0" + hexStr;
            result += hexStr;
        }
        return result.toUpperCase();
    }

    /**
     * 获取16进制日期
     * @return
     */
    public static String getDateHexStr(String dateStr) {
        String result = "";
        System.out.println(dateStr);
        for(Integer i = 0; i < 6; i++) {
            String hexStr = Integer.toHexString(Integer.parseInt(dateStr.substring(i * 2, (i + 1) * 2), 10));
            if (hexStr.length() < 2) hexStr = "0" + hexStr;
            result += hexStr;
        }
        return result.toUpperCase();
    }

    /**
     * @param version     状态
     * @param status    身份
     * @param appId
     * @param orderId  订单号
     * @param secret    加密秘钥
     * @return
     */
    public static String encryption(@NonNull String version, @NonNull String status, @NonNull String appId, @NonNull String orderId, @NonNull String secret) {
        if (StringUtils.isEmpty(version)) {
            throw new IllegalStateException("accounts is required");
        }
        if (StringUtils.isEmpty(status)) {
            throw new IllegalStateException("status is required");
        }
        if (StringUtils.isEmpty(appId)) {
            throw new IllegalStateException("appId is required");
        }
        if (StringUtils.isEmpty(orderId)) {
            throw new IllegalStateException("orderId is required");
        }
        if (StringUtils.isEmpty(secret)) {
            throw new IllegalStateException("secret is required");
        }
        StringBuffer buffer = new StringBuffer();
        buffer.append("A1A2");//固定头部
        buffer.append(version);
        buffer.append(status);
        buffer.append(appId);
        buffer.append(orderId);

        System.out.println(102);
        System.out.println(buffer);
        System.out.println(103);


        //crc16
        String substring = buffer.substring(4, buffer.length());
        char[] code = substring.toCharArray();
        int codeLen = code.length;
        char[] bTempBuf = new char[codeLen];
        char[] bBuffer = new char[codeLen / 2];
        int size = 0;
        for (int i = 0; i < codeLen; i++) {
            bTempBuf[i] = asscii2Hex(code[i]);
        }

        for (int i = 0; i < codeLen / 2; i++) {
            bBuffer[i] = (char) (bTempBuf[size] << 4 | bTempBuf[size + 1]);
            size += 2;
        }

        int dwCalcCrc16 = (genCrc(bBuffer, bBuffer.length));
        int i1 = dwCalcCrc16 & 0xFF;
        int i2 = dwCalcCrc16 >> 8 & 0xFF;
        buffer.append(Integer.toHexString(i1));
        buffer.append(Integer.toHexString(i2));

        //System.out.println(97);
        //System.out.println(buffer);

        //从版本到CRC16间的字节进行加密
        char bInbuf[] = {
                0x12, 0x34, 0x56, 0x78, 0x90
        };
        char[] bCodeBuf1 = qrCodeDecodeKey(bInbuf, bInbuf.length, secret.toCharArray(), secret.toCharArray().length);
        char[] bCodeBuf2 = charToHexStr(bCodeBuf1);


        //System.out.println(98);
        //System.out.println(bCodeBuf2);

        String crc16 = buffer.substring(4, buffer.length()).toUpperCase();
        char[] crcCode = crc16.toCharArray();
        codeLen = crcCode.length;
        char bCrcBuf[] = new char[codeLen];
        char bCrcOutBuf[] = new char[codeLen / 2];
        size = 0;

        for (int i = 0; i < codeLen; i++) {
            bCrcBuf[i] = asscii2Hex(crcCode[i]);
        }

        for (int i = 0; i < codeLen / 2; i++) {
            bCrcOutBuf[i] = (char) (bCrcBuf[size] << 4 | bCrcBuf[size + 1]);
            size += 2;
        }

        //获取到了从版本到CRC16间的字节进行加密的字符串
        char[] chars2 = qrCodeDecodeKey(bCrcOutBuf, bCrcOutBuf.length, bCodeBuf2, bCodeBuf2.length);

        buffer.delete(4, buffer.length());
        //算出长度
        buffer.insert(4, String.format("%04x", chars2.length));
        //格式补全
        for (int i = 0; i < chars2.length; i++) {
            String hexStr = Integer.toHexString(chars2[i]);
            int anInt = Integer.parseInt(hexStr, 16);
            String string = String.format("%02x", anInt);
            buffer.append(string);
        }

        //时间加密
        StringBuffer sb = new StringBuffer();

        sb.append(getDateHexStr());

        //System.out.println(96);
        //System.out.println(sb);

        char[] chars = sb.toString().toUpperCase().toCharArray();
        System.out.println("sb.toString().toUpperCase() = " + sb.toString().toUpperCase());
        codeLen = chars.length;
        char bTimeBuf[] = new char[codeLen];
        char bTimeOutBuf[] = new char[codeLen / 2];

        for (int i = 0; i < codeLen; i++) {
            bTimeBuf[i] = asscii2Hex(chars[i]);
        }
        size = 0;
        for (int i = 0; i < codeLen / 2; i++) {
            bTimeOutBuf[i] = (char) (bTimeBuf[size] << 4 | bTimeBuf[size + 1]);
            size += 2;
        }
        char[] time = qrCodeDecodeKey(bTimeOutBuf, bTimeOutBuf.length, "4SM01ZJ".toCharArray(), "4SM01ZJ".toCharArray().length);
        for (int i = 0; i < time.length; i++) {
            String hexStr = Integer.toHexString(time[i]);
            int anInt = Integer.parseInt(hexStr, 16);
            String string = String.format("%02x", anInt);
            buffer.append(string);
        }
        return buffer.toString().toUpperCase();
    }
}
